import React, { useState, useRef, useMemo, useEffect } from 'react';
import { Switch, Route, Redirect, useHistory } from 'react-router-dom';
import {
  Layout,
  Menu,
  Breadcrumb,
  Spin,
  Typography,
  Dropdown,
  Button,
  Affix,
  Message,
} from '@arco-design/web-react';
import { useSelector } from 'react-redux';
import qs from 'query-string';
import NProgress from 'nprogress';
import Footer from './components/Footer';
import useRoute, { IRoute } from '@/routes';

import getUrlParams from './utils/getUrlParams';
import lazyload from './utils/lazyload';
import { useInstructions } from '@/hooks/checkIn';
import { useModal } from '@/components/Modal';
import { RuleFooter, RuleContent } from '@/components/CheckIn/rule';
import { logout } from '@/services/user';
import { GlobalState } from './store';
import styles from './style/layout.module.less';
import IconLogo from './assets/logo.svg';
import IconArrow from './assets/menu/arrow.svg';
import IconHome from './assets/menu/home.svg';
import IconRacing from './assets/menu/racing.svg';
import IconSignup from './assets/menu/signup.svg';
import IconSponsor from './assets/menu/sponsor.svg';

const MenuItem = Menu.Item;
const SubMenu = Menu.SubMenu;

const Sider = Layout.Sider;
const Content = Layout.Content;

const dropList = (
  <Menu>
    <Menu.Item key="1">
      <Button
        type="primary"
        onClick={() => {
          logout().then((res) => {
            const { status, message, data } = res.data;
            if (status === 200) {
              window.localStorage.clear();
              window.location.href = '/login';
            } else {
              Message.error(message || '服务器出错，请刷新重试');
            }
          });
        }}
      >
        退出登录
      </Button>
    </Menu.Item>
  </Menu>
);

function getIconFromKey(key) {
  switch (key) {
    case 'home':
      return <IconHome className={styles.icon} />;
    case 'racing':
      return <IconRacing className={styles.icon} />;
    case 'signup':
      return <IconSignup className={styles.icon} />;
    case 'sponsor':
      return <IconSponsor className={styles.icon} />;
    default:
      return null;
  }
}

function getFlattenRoutes(routes) {
  const res = [];
  function travel(_routes) {
    _routes.forEach((route) => {
      const visibleChildren = (route.children || []).filter(
        (child) => !child.ignore
      );
      if (route.key && (!route.children || !visibleChildren.length)) {
        try {
          route.component = lazyload(() => import(`./pages/${route.key}`));
          res.push(route);
        } catch (e) {
          console.error(e);
        }
      }
      if (route.children && route.children.length) {
        travel(route.children);
      }
    });
  }
  travel(routes);
  return res;
}

function PageLayout() {
  const urlParams = getUrlParams();
  const history = useHistory();
  const pathname = history.location.pathname;
  const currentComponent = qs.parseUrl(pathname).url.slice(1);

  const { settings, userLoading, userInfo } = useSelector(
    (state: GlobalState) => state
  );
  const { showInstructions } = useInstructions();
  const { showModal } = useModal();

  const [routes, defaultRoute] = useRoute(userInfo?.permissions);
  const defaultSelectedKeys = [currentComponent || defaultRoute];
  const paths = (currentComponent || defaultRoute).split('/');
  const defaultOpenKeys = paths.slice(0, paths.length - 1);

  const [breadcrumb, setBreadCrumb] = useState([]);
  const [selectedKeys, setSelectedKeys] =
    useState<string[]>(defaultSelectedKeys);
  const [openKeys, setOpenKeys] = useState<string[]>(defaultOpenKeys);

  const routeMap = useRef<Map<string, React.ReactNode[]>>(new Map());
  const menuMap = useRef<
    Map<string, { menuItem?: boolean; subMenu?: boolean }>
  >(new Map());

  const menuWidth = settings.menuWidth;

  const showMenu = true;
  const showFooter = settings.footer && urlParams.footer !== false;

  const flattenRoutes = useMemo(() => getFlattenRoutes(routes) || [], [routes]);

  function renderRoutes() {
    routeMap.current.clear();
    return function travel(_routes: IRoute[], level, parentNode = []) {
      return _routes.map((route) => {
        const { breadcrumb = true, ignore } = route;
        const iconDom = getIconFromKey(route.key);
        const titleDom = (
          <div style={{ display: 'flex', alignItems: 'center' }}>
            {iconDom} {route.name}
          </div>
        );

        routeMap.current.set(
          `/${route.key}`,
          breadcrumb ? [...parentNode, route.name] : []
        );

        const visibleChildren = (route.children || []).filter((child) => {
          const { ignore, breadcrumb = true } = child;
          if (ignore || route.ignore) {
            routeMap.current.set(
              `/${child.key}`,
              breadcrumb ? [...parentNode, route.name, child.name] : []
            );
          }

          return !ignore;
        });

        if (ignore) {
          return '';
        }
        if (visibleChildren.length) {
          menuMap.current.set(route.key, { subMenu: true });
          return (
            <SubMenu key={route.key} title={titleDom} selectable={false}>
              {travel(visibleChildren, level + 1, [...parentNode, route.name])}
            </SubMenu>
          );
        }
        menuMap.current.set(route.key, { menuItem: true });
        return <MenuItem key={route.key}>{titleDom}</MenuItem>;
      });
    };
  }

  function handleShowModal() {
    showModal({
      title: null,
      children: <RuleContent />,
      footer: <RuleFooter />,
    });
  }

  function onClickMenuItem(key) {
    const currentRoute = flattenRoutes.find((r) => r.key === key);
    const component = currentRoute.component;
    const preload = component.preload();
    NProgress.start();
    preload.then(() => {
      history.push(currentRoute.path ? currentRoute.path : `/${key}`);
      NProgress.done();
    });
  }

  const paddingLeft = showMenu ? { paddingLeft: menuWidth } : {};
  const paddingTop = {};
  //  showNavbar ? { paddingTop: navbarHeight } : {};
  const paddingStyle = { ...paddingLeft, ...paddingTop };

  function updateMenuStatus() {
    const pathKeys = pathname.split('/');
    const newSelectedKeys: string[] = [];
    const newOpenKeys: string[] = [...openKeys];
    while (pathKeys.length > 0) {
      const currentRouteKey = pathKeys.join('/');
      const menuKey = currentRouteKey.replace(/^\//, '');
      const menuType = menuMap.current.get(menuKey);
      if (menuType && menuType.menuItem) {
        newSelectedKeys.push(menuKey);
      }
      if (menuType && menuType.subMenu && !openKeys.includes(menuKey)) {
        newOpenKeys.push(menuKey);
      }
      pathKeys.pop();
    }
    setSelectedKeys(newSelectedKeys);
    setOpenKeys(newOpenKeys);
  }

  useEffect(() => {
    const routeConfig = routeMap.current.get(pathname);
    setBreadCrumb(routeConfig || []);
    updateMenuStatus();
  }, [pathname]);

  // 展示入住说明弹窗
  useEffect(() => {
    if (showInstructions()) {
      handleShowModal();
    }
  }, []);

  return (
    <Layout className={styles.layout}>
      {/* <div
        className={cs(styles['layout-navbar'], {
          [styles['layout-navbar-hidden']]: !showNavbar,
        })}
      >
        <Navbar show={showNavbar} />
       
      </div> */}

      {userLoading ? (
        <Spin className={styles['spin']} />
      ) : (
        <Layout>
          {showMenu && (
            <Sider
              className={styles['layout-sider']}
              width={menuWidth}
              trigger={null}
              collapsible
              breakpoint="xl"
              style={paddingTop}
            >
              <div className={styles['menu-wrapper']}>
                <IconLogo style={{ margin: '28px 20px 8px' }} />
                <Menu
                  levelIndent={40}
                  icons={{
                    horizontalArrowDown: (
                      <div style={{ display: 'flex' }}>
                        <IconArrow />
                      </div>
                    ),
                  }}
                  onClickMenuItem={onClickMenuItem}
                  selectedKeys={selectedKeys}
                  openKeys={openKeys}
                  onClickSubMenu={(_, openKeys) => setOpenKeys(openKeys)}
                >
                  {renderRoutes()(routes, 1)}
                </Menu>
              </div>
            </Sider>
          )}
          <Layout className={styles['layout-content']} style={paddingStyle}>
            <Affix offsetTop={0}>
              <div className={styles['layout-navbar']}>
                <div className={styles.left}>
                  <Typography.Title heading={5} style={{ margin: '0' }}>
                    欢迎登录👋
                  </Typography.Title>
                  <Typography.Text type={'secondary'}>
                    宝宝树旗下专注青少年体育活动赛事报名平台
                  </Typography.Text>
                </div>
                <div className={styles.right}>
                  <Dropdown droplist={dropList} position="br">
                    <Typography.Text>{userInfo.userName}</Typography.Text>
                    <IconArrow />
                  </Dropdown>
                </div>
              </div>
            </Affix>
            <div className={styles['layout-content-wrapper']}>
              {!!breadcrumb.length && (
                <div className={styles['layout-breadcrumb']}>
                  <Breadcrumb>
                    {breadcrumb.map((node, index) => (
                      <Breadcrumb.Item key={index}>{node}</Breadcrumb.Item>
                    ))}
                  </Breadcrumb>
                </div>
              )}
              <Content>
                <Switch>
                  {flattenRoutes.map((route, index) => {
                    return (
                      <Route
                        key={index}
                        path={`/${route.key}`}
                        component={route.component}
                      />
                    );
                  })}
                  <Route exact path="/">
                    <Redirect to={`/${defaultRoute}`} />
                  </Route>
                  <Route
                    path="*"
                    component={lazyload(() => import('./pages/exception/403'))}
                  />
                </Switch>
              </Content>
            </div>
            {showFooter && <Footer />}
          </Layout>
        </Layout>
      )}
    </Layout>
  );
}

export default PageLayout;
